﻿package com.luyuan.crm.sale.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.hibernate.proxy.HibernateProxyHelper;

import com.luyuan.crm.member.model.Customer;
import com.luyuan.crm.member.model.Member;
import com.luyuan.crm.member.model.MemberCoupon;
import com.luyuan.crm.member.model.MemberIntegral;
import com.luyuan.crm.member.model.NoAccountCustomer;
import com.luyuan.crm.member.model.Region;
import com.luyuan.crm.member.service.MemberCouponService;
import com.luyuan.crm.member.service.MemberIntegralService;
import com.luyuan.crm.member.service.RegionService;
import com.luyuan.crm.promotion.MemberIntegralPromotionService;
import com.luyuan.crm.sale.model.Delivery;
import com.luyuan.crm.sale.model.ExpressCompany;
import com.luyuan.crm.sale.model.Order;
import com.luyuan.crm.sale.model.OrderProduct;
import com.luyuan.crm.sale.model.OrderRecord;
import com.luyuan.crm.sale.model.OrderStatus;
import com.luyuan.crm.sale.model.OrderType;
import com.luyuan.crm.sale.service.OrderRecordService;
import com.luyuan.crm.sale.service.OrderService;
import com.luyuan.crm.sms.Constant;
import com.luyuan.crm.sms.service.SmsService;
import com.luyuan.crm.task.TaskDaily;
import com.luyuan.crm.task.TaskDailyService;
import com.luyuan.crm.user.Party;
import com.luyuan.crm.user.service.PartyService;
import com.ruijie.components.security.model.AppUser;
import com.ruijie.components.setting.service.SettingService;
import com.ruijie.foundation.dao.support.HibernateEntityDao;
import com.ruijie.foundation.dao.support.HibernateUtils;
import com.ruijie.foundation.query.Page;
import com.ruijie.foundation.query.criteria.CriteriaQueryTemplate;
import com.ruijie.foundation.query.criteria.CriteriaTemplate;
import com.ruijie.foundation.security.AppUserContext;
import com.ruijie.util.StringUtils;

@SuppressWarnings("unchecked")
public class OrderServiceImpl extends HibernateEntityDao<Order> implements OrderService {

    private PartyService partyService;

    private MemberIntegralPromotionService memberIntegralPromotionService;

    private MemberIntegralService memberIntegralService;

    private MemberCouponService memberCouponService;

    private OrderRecordService orderRecordService;

    private SmsService smsService;

    private SettingService settingService;

    private RegionService regionService;

    private TaskDailyService taskDailyService;

    @Override
    public Order getById(String id) {
        return super.safeGet(id);
    }

    @Override
    public Page pagedQuery(CriteriaTemplate criteria, int pageNo, int pageSize,
            List<org.hibernate.criterion.Order> orders) {
        if (orders == null) {
            orders = new ArrayList<org.hibernate.criterion.Order>();
        }
        if (orders.isEmpty()) {
            orders.add(org.hibernate.criterion.Order.asc("createTime"));
        }
        CriteriaQueryTemplate cqt = new CriteriaQueryTemplate(getSessionFactory());
        return cqt.pagedQuery(criteria, pageNo, pageSize, orders);
    }

    @Override
    public List<Order> findByMember(Member member) {
        List<Order> orders = null;
        orders = find("From Order where member=?", member);
        return orders;
    }

    @Override
    public List<Order> findByMemberId(String memberId) {
        List<Order> orders = null;
        orders = find("From Order where member.id=?", memberId);
        return orders;
    }

    @Override
    public List<Order> findByOrderStatus(OrderStatus orderStatus, Date beginDate, Date endDate) {
        return find("from Order o where o.orderStatus = ? and o.createTime between ? and ?", orderStatus, beginDate,
                endDate);
    }

    @Override
    public List<Order> findByExpressCompany(String uuid, ExpressCompany expressCompany, Date beginDate, Date endDate) {
        Criteria criteria = createCriteria(Restrictions.eq("orderStatus", OrderStatus.VERIFIED));

        if (StringUtils.isNotEmpty(uuid)) {
            criteria.add(Restrictions.eq("id", uuid));
        }

        if (expressCompany != null) {
            criteria.createCriteria("delivery", "d").add(Restrictions.eq("d.expressCompany", expressCompany));
        }

        if (beginDate != null && endDate == null) {
            criteria.add(Restrictions.gt("d.createTime", beginDate));
        }
        else if (beginDate == null && endDate != null) {
            criteria.add(Restrictions.lt("d.createTime", endDate));
        }
        else if (beginDate != null && endDate != null) {
            criteria.add(Restrictions.between("d.createTime", beginDate, endDate));
        }

        return criteria.list();
    }

    @Override
    public void createOrder(Order order) {
        Delivery delivery = order.getDelivery();
        delivery.setOrder(order);
        Region region = regionService.getByRegion(delivery.getDeliveryAddress().getProvince(), delivery
                .getDeliveryAddress().getCity(), delivery.getDeliveryAddress().getRegion());
        if (region != null) {
            delivery.getDeliveryAddress().setPostCode(region.getId());
        }

        AppUser appUser = (AppUser) AppUserContext.getCurrentUser();
        order.setSaleman(partyService.getByAppUser(appUser));
        order.setSaleName(order.getSaleman().getUserName());
        order.setSupport(null);
        order.setCreateTime(new Date());
        order.setOrderStatus(OrderStatus.CREATED);

        save(order);

        promote(order);

        createOrderRecord(order, "创建订单！");
    }

    private void promote(Order order) {
        if (HibernateUtils.resolveRealObject(order.getCustomer()) instanceof Member) {
            int integralDeduction = order.getOrderPromotion().getIntegralDeduction();
            for (OrderProduct orderProduct : order.getOrderProducts()) {
                if (orderProduct.getExchangeIntegral() > 0) {
                    integralDeduction += orderProduct.getExchangeIntegral();
                }
            }
            if (integralDeduction > 0) {
                memberIntegralService.updateMemberCurrentIntegral(
                        memberIntegralService.getMemberIntegral(order.getCustomer()), -integralDeduction,
                        "订单" + order.getId() + "使用。");
            }

            MemberCoupon coupon = order.getOrderPromotion().getCouponDeduction();
            if (coupon != null && coupon.getAmount() > 0) {
                memberCouponService.userMemberCoupon((Member) order.getCustomer(), coupon.getCouponType(),
                        coupon.getAmount(), "订单" + order.getId() + "使用。");
            }
        }
    }

    @Override
    public void increaseExportCount(Order order) {
        order.setExportCount(order.getExportCount() + 1);

        update(order);
    }

    @Override
    public void increasePrintCount(Order order) {
        order.setPrintCount(order.getPrintCount() + 1);

        update(order);

        createOrderRecord(order, "打印订单详细信息。");
    }

    @Override
    public void updateOrder(Order order) {
        order.setOrderStatus(OrderStatus.CREATED);
        if (order.getOrderPromotion().getId() == null) {
            save(order.getOrderPromotion());
        }

        if (HibernateUtils.resolveRealObject(order.getCustomer()) instanceof Member) {
            // old
            Order oldOrder = (Order) findUniqueBy("id", order.getId());
            int oldIntegralDeduction = oldOrder.getOrderPromotion().getIntegralDeduction();
            for (OrderProduct orderProduct : oldOrder.getOrderProducts()) {
                if (orderProduct.getExchangeIntegral() > 0) {
                    oldIntegralDeduction += orderProduct.getExchangeIntegral();
                }
            }
            int integralDeduction = order.getOrderPromotion().getIntegralDeduction();
            for (OrderProduct orderProduct : order.getOrderProducts()) {
                if (orderProduct.getExchangeIntegral() > 0) {
                    integralDeduction += orderProduct.getExchangeIntegral();
                }
            }

            if (integralDeduction != oldIntegralDeduction) {
                memberIntegralService.updateMemberCurrentIntegral(
                        memberIntegralService.getMemberIntegral(order.getCustomer()), oldIntegralDeduction
                                - integralDeduction, "订单" + order.getId() + "更新。");
            }

            MemberCoupon oldCoupon = oldOrder.getOrderPromotion().getCouponDeduction();
            MemberCoupon coupon = order.getOrderPromotion().getCouponDeduction();
            if (oldCoupon != null && coupon != null && oldCoupon.getAmount() == coupon.getAmount()
                    && oldCoupon.getCouponType() == coupon.getCouponType()) {
                // 没有变化
            }
            else {
                if (oldCoupon != null && oldCoupon.getAmount() > 0) {
                    oldCoupon.setId(null);
                    oldCoupon.setMember((Member) HibernateUtils.resolveRealObject(order.getCustomer()));
                    memberCouponService.addMemberCoupon(oldCoupon, "订单" + order.getId() + "更新。");
                }
                if (coupon != null && coupon.getAmount() > 0) {
                    coupon.setId(null);
                    coupon.setMember((Member) HibernateUtils.resolveRealObject(order.getCustomer()));
                    memberCouponService.userMemberCoupon(
                            (Member) HibernateUtils.resolveRealObject(order.getCustomer()), coupon.getCouponType(),
                            coupon.getAmount(), "订单" + order.getId() + "更新。");
                }
            }
            evit(oldOrder);
        }

        update(order);
        createOrderRecord(order, "修改订单状态为：" + OrderStatus.CREATED.getName());
    }

    @Override
    public void verifyOrder(Order order, String remarks) {
        order.setOrderStatus(OrderStatus.VERIFIED);
        update(order);

        createOrderRecord(order, "修改订单状态为：" + OrderStatus.VERIFIED.getName(), remarks);
    }

    private void sendDeliverMessage(Order order) {
        // Customer customer = order.getCustomer();
        String[] objects = new String[4];
        // 会员名
        objects[0] = order.getDelivery().getReceiver();
        // 快递方式
        objects[1] = order.getDelivery().getExpressCompany().getName();
        // 金额
        objects[2] = String.valueOf(order.getAmount());
        // 快递编号
        objects[3] = order.getDelivery().getDeliveryNumber();

        String content = settingService.getSetting(Constant.SMS_CONTENT_SHIPPING).getValue();
        content = content.replaceAll("#\\{会员姓名\\}", objects[0]).replaceAll("#\\{快递方式\\}", objects[1])
                .replaceAll("#\\{订单金额\\}", objects[2]).replaceAll("#\\{物流单号\\}", objects[3]);
        smsService.sendMessage(order.getDelivery().getDeliveryPhone(), content);
    }

    @Override
    public void deliverOrder(Order order, String remarks) {
        order.setOrderStatus(OrderStatus.DELIVERED);
        order.getDelivery().setDeliveryDate(new Date());
        getHibernateTemplate().update(order.getDelivery());
        update(order);

        sendDeliverMessage(order);

        createOrderRecord(order, "修改订单状态为：" + OrderStatus.DELIVERED.getName(), remarks);
    }

    @Override
    public void changeExpressOrder(Order order, String remarks) {
        getHibernateTemplate().update(order.getDelivery());
        update(order);

        sendChangeExpressMessage(order);

        createOrderRecord(order, "修改快递方式为：" + order.getDelivery().getExpressCompany().getName(), remarks);
    }

    private void sendChangeExpressMessage(Order order) {
        // Customer customer = order.getCustomer();
        String[] objects = new String[4];
        // 会员名
        objects[0] = order.getDelivery().getReceiver();
        // 快递方式
        objects[1] = order.getDelivery().getExpressCompany().getName();
        // 金额
        objects[2] = String.valueOf(order.getAmount());
        // 快递编号
        objects[3] = order.getDelivery().getDeliveryNumber();

        String content = settingService.getSetting(Constant.SMS_CONTENT_CHANGE_EXPRESS).getValue();
        content = content.replaceAll("#\\{会员姓名\\}", objects[0]).replaceAll("#\\{快递方式\\}", objects[1])
                .replaceAll("#\\{订单金额\\}", objects[2]).replaceAll("#\\{物流单号\\}", objects[3]);
        smsService.sendMessage(order.getDelivery().getDeliveryPhone(), content);
    }

    @Override
    public void receivedOrder(Order order, String remarks) {
        order.setOrderStatus(OrderStatus.RECEIVED);
        update(order);

        // 如果当前积分是0的会员，才发短信通知
        Customer customer = order.getCustomer();
        MemberIntegral memberIntegral = memberIntegralService.getMemberIntegral(customer);
        if (memberIntegral.getTotalIntegral() == 0) {
            String[] objects = new String[2];
            // 会员名
            objects[0] = order.getCustomer().getName();
            // 会员积分
            objects[1] = String.valueOf((int) order.getAmount());

            String content = settingService.getSetting(Constant.SMS_CONTENT_RECEIVE).getValue();
            content = content.replaceAll("#\\{会员姓名\\}", objects[0]).replaceAll("#\\{会员积分\\}", objects[1]);
            smsService.sendMessage(order.getCustomer().getMobile(), content);
        }

        memberIntegralPromotionService.updateIntegral(order);

        // 配方，执行期结束时做回访
        if (order.getOrderType() == OrderType.FORMULA) {
            TaskDaily taskDaily = new TaskDaily();
            taskDaily.setCreator("system");
            taskDaily.setCustomer(customer);

            Calendar ca = Calendar.getInstance();
            ca.setTime(new Date());
            if (order.getOrderFormula().getDays() > 30) {
                taskDaily.setDescription("配方(" + order.getOrderFormula().getName() + ")执行期("
                        + order.getOrderFormula().getDays() + "天)，于10天后执行完成。");
                ca.add(Calendar.DATE, order.getOrderFormula().getDays() - 10);
            }
            else if (order.getOrderFormula().getDays() > 15) {
                taskDaily.setDescription("配方(" + order.getOrderFormula().getName() + ")执行期("
                        + order.getOrderFormula().getDays() + "天)，于5天后执行完成。");
                ca.add(Calendar.DATE, order.getOrderFormula().getDays() - 5);
            }
            else {
                taskDaily.setDescription("配方(" + order.getOrderFormula().getName() + ")执行期("
                        + order.getOrderFormula().getDays() + "天)，即将执行完成。");
                ca.add(Calendar.DATE, order.getOrderFormula().getDays());
            }
            Date excuteDate = ca.getTime();
            taskDaily.setExpectedTime(excuteDate);

            Member member = null;
            customer = (Customer) getHibernateTemplate().get(Customer.class, customer.getId());
            Class<?> customerClazz = HibernateProxyHelper.getClassWithoutInitializingProxy(customer);
            if (customerClazz == Member.class) {
                member = (Member) customer;
            }
            else if (customerClazz == NoAccountCustomer.class) {
                member = ((NoAccountCustomer) customer).getAccountHolder();
            }
            if (member.getSupport() != null) {
                taskDaily.setParty(member.getSupport());
            }
            taskDailyService.createTaskDaily(taskDaily);
        }

        createOrderRecord(order, "修改订单状态为：" + OrderStatus.RECEIVED.getName(), remarks);
    }

    @Override
    public void rejectOrder(Order order, String remarks) {
        order.setOrderStatus(OrderStatus.REJECTED);
        update(order);

        createOrderRecord(order, "修改订单状态为：" + OrderStatus.REJECTED.getName(), remarks);
    }

    @Override
    public void cancelOrder(Order order, String remarks) {
        order.setOrderStatus(OrderStatus.CANCELLED);
        update(order);

        if (HibernateUtils.resolveRealObject(order.getCustomer()) instanceof Member) {
            int integralDeduction = order.getOrderPromotion().getIntegralDeduction();
            for (OrderProduct orderProduct : order.getOrderProducts()) {
                if (orderProduct.getExchangeIntegral() > 0) {
                    integralDeduction += orderProduct.getExchangeIntegral();
                }
            }
            if (integralDeduction > 0) {
                memberIntegralService.updateMemberCurrentIntegral(
                        memberIntegralService.getMemberIntegral(order.getCustomer()), integralDeduction,
                        "订单" + order.getId() + "取消。");
            }

            MemberCoupon coupon = order.getOrderPromotion().getCouponDeduction();
            if (coupon != null && coupon.getAmount() > 0) {
                coupon.setId(null);
                coupon.setMember((Member) HibernateUtils.resolveRealObject(order.getCustomer()));
                memberCouponService.addMemberCoupon(coupon, "订单" + order.getId() + "取消。");
            }
        }
        createOrderRecord(order, "修改订单状态为：" + OrderStatus.CANCELLED.getName(), remarks);
    }

    @Override
    public void returnOrder(Order order, String remarks) {
        order.setOrderStatus(OrderStatus.UPDATING);
        update(order);

        createOrderRecord(order, "修改订单状态为：" + OrderStatus.UPDATING.getName(), remarks);
    }

    @Override
    public void appointSupport(Order order, Party support) {
        order.setSupport(support);
        update(order);

        createOrderRecord(order, "指定售后人员：" + support.getUserName());
    }

    private void createOrderRecord(Order order, String operation) {
        createOrderRecord(order, operation, null);
    }

    private void createOrderRecord(Order order, String operation, String remarks) {
        AppUser appUser = (AppUser) AppUserContext.getCurrentUser();

        OrderRecord orderRecord = new OrderRecord();
        orderRecord.setOrder(order);
        orderRecord.setOperator(partyService.getByAppUser(appUser));
        orderRecord.setOperation(operation);
        orderRecord.setOperateTime(new Date());
        orderRecord.setRemarks(remarks);

        orderRecordService.save(orderRecord);
    }

    public void setPartyService(PartyService partyService) {
        this.partyService = partyService;
    }

    public void setOrderRecordService(OrderRecordService orderRecordService) {
        this.orderRecordService = orderRecordService;
    }

    public void setSettingService(SettingService settingService) {
        this.settingService = settingService;
    }

    public void setSmsService(SmsService smsService) {
        this.smsService = smsService;
    }

    public void setMemberIntegralService(MemberIntegralService memberIntegralService) {
        this.memberIntegralService = memberIntegralService;
    }

    public void setMemberIntegralPromotionService(MemberIntegralPromotionService memberIntegralPromotionService) {
        this.memberIntegralPromotionService = memberIntegralPromotionService;
    }

    public void setRegionService(RegionService regionService) {
        this.regionService = regionService;
    }

    @Override
    public void backupOrder() {
    }

    public void setMemberCouponService(MemberCouponService memberCouponService) {
        this.memberCouponService = memberCouponService;
    }

    public void setTaskDailyService(TaskDailyService taskDailyService) {
        this.taskDailyService = taskDailyService;
    }

    public TaskDailyService getTaskDailyService() {
        return taskDailyService;
    }
}
